package ch.exm.storm.conditions.arguments;

import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

import ch.exm.storm.collections.BoundedFifoMap;

public class ArgumentsFactory {

	private ArgumentsFactory() { }
	
	// ////////////////////////////////////////////////////////////////////////
	// /// Factory
	// ////////////////////////////////////////////////////////////////////////
	
	private static Integer argumentCounter = 0;
	
	public static <I> I createArgument(Class<I> clazz) {
		Integer rootArgumentId = argumentCounter++;
		I argument = createArgument(rootArgumentId, clazz, new ArrayList<Invocation>());
		bindArgument(argument, new Argument(rootArgumentId, clazz));
		return argument;
	}
	
	@SuppressWarnings("unchecked")
	static <I> I createArgument(Integer rootArgumentId, Class<I> clazz, List<Invocation> invocationSequence) {
		return (I)Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] {clazz}, new ProxyArgument(rootArgumentId, clazz, invocationSequence));
	}
	
	// ////////////////////////////////////////////////////////////////////////
	// /// Placeholders
	// ////////////////////////////////////////////////////////////////////////
	
	private static ThreadLocal<BoundedFifoMap<Object, Argument>> argumentsStore = new ThreadLocal<BoundedFifoMap<Object, Argument>>() {
        protected BoundedFifoMap<Object, Argument> initialValue() {
            return new BoundedFifoMap<Object, Argument>();
        }
    };
    
    static void bindArgument(Object placeholder, Argument argument) {
    	argumentsStore.get().put(placeholder, argument);
    }
    
    public static Argument getActualArgument(Object placeholder) {
    	return argumentsStore.get().get(placeholder);
    }
}
